﻿using System;
using System.Collections.Generic;
using System.Text;
using Eqwww.Code;
using Eqwww.Domain.Models.SystemManage;
using Eqwww.Data;
using Microsoft.AspNetCore.Http;
using System.Linq;
using System.Security.Claims;
using Newtonsoft.Json;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Eqwww.Domain.Models.Identity;
using System.Security.Cryptography.X509Certificates;

namespace Eqwww.App.SystemManage
{
    public class DatabaseLogApp
    {
        private IHttpContextAccessor _httpContextAccessor;
        private ApplicationDbContext _context;
        public DatabaseLogApp(ApplicationDbContext context, IHttpContextAccessor httpContextAccessor)
        {
            _context = context;
            _httpContextAccessor = httpContextAccessor;
        }

        private string OperatorId()
        {
            if (_httpContextAccessor.HttpContext.User.Identity.IsAuthenticated)
            {
                var claim = _httpContextAccessor.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier);
                if (claim != null)
                    return claim.Value;
            }
            return null;

        }

        private string GetIp()
        {
            return _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
        }

        public IEnumerable<DatabaseLogModel> GetObjectHistory(string objectId, int count)
        {
            return _context.Sys_DatabaseLogs.Where(x => x.ObjectId == objectId).OrderByDescending(x => x.CreateTime).Take(count);
        }


        public async Task<DatabaseLogModel> GetAsync(string id)
        {
            return await _context.Sys_DatabaseLogs.FirstOrDefaultAsync(x => x.Id == id);
        }

        public void LogInformation(string objectId, DbLogOperationType dbLogOperationType, string message, object jsonData=null)
        {
            var log = new DatabaseLogModel
            {
                Id=Guid.NewGuid().ToString(),
                CreateTime = DateTime.Now,
                OperatorId = OperatorId(),
                ObjectId = objectId,
                ObjectType = jsonData==null?null:jsonData.GetType().ToString(),
                DbLogOperationType = dbLogOperationType,
                OperateTime = DateTime.Now,
                Information = message,
                Ip=GetIp()
            };
            if (jsonData != null)
                log.JsonData = Newtonsoft.Json.JsonConvert.SerializeObject(jsonData);

            _context.Add(log);
        }

        public void LogCreateInformation(string objectId, object jsonData = null, string message = null)
        {
            LogInformation(objectId, DbLogOperationType.Create, message, jsonData);
        }

        public void LogUpdateInformation(string objectId, object jsonData = null, string message=null)
        {
            LogInformation(objectId, DbLogOperationType.Update, message, jsonData);
        }

        public void LogRemoveInformation(string objectId, object jsonData = null, string message=null)
        {
            LogInformation(objectId, DbLogOperationType.DeleteSoftly, message, jsonData);
        }

        public void LogDeleteInformation(string objectId, object jsonData = null, string message=null)
        {
            LogInformation(objectId, DbLogOperationType.DeletePhy, message, jsonData);
        }

        /// <summary>
        /// 记录一条登录日志
        /// </summary>
        public void LogInformationLogin(string userId, string message)
        {
            var log = new DatabaseLogModel
            {
                Id = Guid.NewGuid().ToString(),
                CreateTime = DateTime.Now,
                OperatorId = userId,

                DbLogOperationType = DbLogOperationType.Login,
                OperateTime = DateTime.Now,
                Information = message,
                Ip = GetIp()
            };
            _context.Add(log);
            _context.SaveChanges();
        }
        /// <summary>
        /// 记录一条注销登录日志
        /// </summary>
        public void LogInformationLogout(UserModel user)
        {
            var log = new DatabaseLogModel
            {
                Id = Guid.NewGuid().ToString(),
                CreateTime = DateTime.Now,
                OperatorId = user.Id,
                
                DbLogOperationType = DbLogOperationType.Logout,
                OperateTime = DateTime.Now,
                Information = "["+user.UserName+"]退出登录。",
                Ip = GetIp()
            };
            
            _context.Add(log);
            _context.SaveChanges();
        }

        public IQueryable<DatabaseLogModel> IQueryable()
        {
            return _context.IQueryable<DatabaseLogModel>();
        }

        public IList<DatabaseLogModel> GetPagedList(Pagination pagination, string keyword, DbLogOperationType? DbLogOperationType, DateTime? btime, DateTime? etime)
        {
            var exp = ExtLinq.True<DatabaseLogModel>();
            if (!string.IsNullOrEmpty(keyword))
                exp = exp.And(x => x.Operator.RealName.Contains(keyword) || x.Operator.UserName.Contains(keyword));
            if (DbLogOperationType.HasValue)
                exp = exp.And(x => x.DbLogOperationType == DbLogOperationType);
            if (btime.HasValue)
                exp = exp.And(x => x.CreateTime >= btime);
            if (etime.HasValue)
                exp = exp.And(x => x.CreateTime <= etime);
            var data = _context.FindQueryable(exp, pagination)
                .Include(x => x.Operator);
            return data.ToList();
        }

        public ModelResult ClearLog(int ck)
        {
            var sql = ExtLinq.True<DatabaseLogModel>();
            if (ck == 0)
                sql = sql.And(x => x.CreateTime <= DateTime.Now.AddYears(-1));
            else if (ck == 1)
                sql = sql.And(x => x.CreateTime <= DateTime.Now.AddMonths(-6));
            else if (ck == 2)
                sql = sql.And(x => x.CreateTime <= DateTime.Now.AddMonths(-3));
            else if (ck == 3)
                sql = sql.And(x => x.CreateTime <= DateTime.Now.AddMonths(-1));
            else
                sql = sql.And(x => x.CreateTime > DateTime.Now);

            var models = _context.Set<DatabaseLogModel>().Where(sql).AsNoTracking();
            _context.RemoveRange(models);
            _context.SaveChanges();
            return Common.SuccessResult();
            
        }
    }
}
